#!/usr/bin/python3
# -*- coding:utf-8 -*-
""""
   @Author: 叶建伟
   @Email: yejw46507@hundsun.com
   @Time: 2023/7/3 14:06
   @File: restartServer.py
   效能环境重启反洗钱5.0组件和服务
"""
import json
import os
import time
from time import sleep
import requests

from BladeFerm.Lib.LocalLogger import logger_local as logger
from BladeFerm.Lib.Common import logger as logger_blade
from DataTest.env import Env

headers = {
        'Connection': 'keep-alive',
        'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
    }

# 存储环境对象，用于后续调用。结构：{envName：SeeService}
ENVObject = dict()


class RequestFailed(Exception):
    pass


class APIRequset:
    def __init__(self, url, data, headers):
        self.url = url
        self.data = data
        self.headers = headers
        self.session = requests.session()

    def doPost(self):
        try:
            logger_blade.debug(f"POST请求信息 url:{self.url}，请求头：{self.headers}，参数：{self.data}")
            rsp = self.session.post(self.url, data=self.data, headers=self.headers)
            logger_blade.debug(f"POST响应结果：{rsp.json()}, {rsp.text}")
            if rsp.status_code != 200:
                raise RequestFailed('%s failed', rsp.text)
        except requests.RequestException as e:
            raise RequestFailed('request failed: %s' % str(e))
        else:
            return rsp

    def doGet(self):
        try:
            logger_blade.debug(f"GET请求信息 url:{self.url}，请求头：{self.headers}，参数：{self.data}")
            rsp = self.session.get(self.url, headers=self.headers, params=self.data)
            logger_blade.debug(f"GET响应结果：{rsp.text}")
            if rsp.status_code != 200:
                raise RequestFailed('%s failed', rsp.text)
        except requests.RequestException as e:
            raise RequestFailed('request failed: %s' % str(e))
        else:
            return rsp

"""
通过url获取登录token
"""


def getToken(url):
    data = None
    while True:
        test = APIRequset(url, data, headers=None)  # 先创建对象
        response = test.doGet()  # 再调用方法
        result = response.cookies.get_dict()
        if result =={}:
            continue
        else:
            headers['Cookie'] = 'JSESSIONID=' + result['JSESSIONID']
            break
    urlLogin = url.replace('/app.htm', '/system/auth.json')
    test1 = APIRequset(urlLogin, data, headers)  # 先创建对象
    loginResponse = test1.doPost()
    jsonResponse = json.loads(loginResponse.text)
    token = "Bearer "+jsonResponse["data"]["token"]
    logger_blade.debug(f"token: {token}")
    return token

"""
查询服务信息，获取服务ID
"""
def getServer(url,token,keyWord):
    headers['Authorization'] = token
    getUrl = url.replace("/app.htm","/dssp/application/authority/query.json")
    data = {'pageNo': '1', 'pageSize': '15', 'name': keyWord}
    test = APIRequset(getUrl, data, headers)
    return test.doPost()

"""
查询服务状态
"""
def getServerStatics(url,token,keyWord):
    headers['Authorization'] = token
    # getUrl = url.replace("/app.htm","/dssp/application/getStatics.json")
    # data = {'name': keyWord}
    getUrl = url.replace("/app.htm", "/dssp/log/getLastLogBySystemIds.json")
    data = {'systemIds': keyWord}
    test = APIRequset(getUrl, data, headers)
    return test.doPost()


def restartServer(url, token, keyWord):
    """
    重启服务
    :param url:
    :param token:
    :param keyWord:
    :return:
    """
    headers['Authorization'] = token
    getUrl = url.replace("/app.htm", "/dssp/application/console/restartApp.json")
    data = {'forceKill': 'false', 'appId':  keyWord}
    test = APIRequset(getUrl, data, headers)
    return test.doPost()


def runServer(url, token, id, name):
    """
    部署服务
    :param url:
    :param token:
    :param id:
    :param name:
    :return:
    """
    headers['Authorization'] = token
    url = url.split('#', 1)[0]
    getUrl = url.replace("/app.htm","/dssp/config/runDeploy.json")
    data = {'applicationId': id, 'name':  name,'registSystem':False,'isForceReinstall':False}
    test = APIRequset(getUrl, data, headers)
    response = test.doPost()
    logger.info(response.text)
    result = json.loads(response.text)
    if result['data']['serial_no']:
        return response
    else:
        data = {'applicationId': id, 'name': name, 'registSystem': False, 'isForceReinstall': True}
        test = APIRequset(getUrl, data, headers)
        return test.doPost()


def restart(url, keyWordList, env=None):
    """
    重启服务并检查重启状态
    :param url:
    :param keyWordList:
    :param env:
    :return:
    """
    see_config = dict()
    if env:
        EnvObject = Env(env)
        see_config = EnvObject.seeConfig
        url = see_config.get('url')
    token = getToken(url)
    flag = True
    for keyWord in keyWordList:
        if keyWord in ['ZooKeeper', 'RabbitMQ', 'Redis']:
            component_list = getComponent(url, token)
            instanceId = component_list.get(keyWord)
            res_list = restartComponent(url, token, instanceId).json()
            if res_list.get('message') == 'success':
                logger.info(f"============组件{keyWord}开始重启！！=========")
                for i in range(12):
                    res_status = getComponentStatus(url, token, instanceId).json()
                    # logger.info(res_status['data'][f'#{instanceId}']['runningState'])
                    if res_status['data'][f'#{instanceId}']['runningState'] == '100':
                        logger.info(f"============组件{keyWord}重启成功！！=========")
                        # return True
                    else:
                        time.sleep(10)
                        if i == 11:
                            logger.info(f"============注意！！！组件{keyWord} 2分钟内未重启成功！！=========")
                            flag = False
            else:
                logger.info(f"============组件{keyWord}重启失败！！=========")
                # return False
                flag = False
        response = getServer(url, token, keyWord)
        result = json.loads(response.text)
        # logger.info(result)
        if result['data']['items']:

            id = result['data']['items'][0]['id']
            if keyWord in ['amlps-server', 'amlwl-server', 'amlcom-server', 'amlcp-server', 'amlcrs-server']:
                runServer(url, token, id, 'hsrcm-'+keyWord)
                logger.info(f"============{result['data']['items'][0]['name']}开始重新部署！！=========")
            else:
                restartServer(url, token, id)
                logger.info(f"============{result['data']['items'][0]['name']}开始重启！！=========")
            temp = 0
            while temp < 36:
                sleep(10)
                response = getServerStatics(url, token, id)
                result1 = response.json()
                # logger.info(result1)
                # if result1['data']['success'] == 1:
                if result1['data'][0]['filnal_status'] == 0:
                    logger.info(f"============{result['data']['items'][0]['name']}重启成功！！=========")
                    break
                else:
                    temp = temp + 1
            if temp == 36:
                logger.info(f"============注意！！{result['data']['items'][0]['name']} 六分钟内未启动完成！！=========")
                flag = False
        else:
            logger.info(f"============服务不存在，重启失败！=========")
            flag = False
        # if not flag:
        #     return flag
    return flag



"""
重启服务并检查重启状态
"""
def checkServerStatus(url, keyWord, env=None):
    logger.info(f"current check server : {keyWord}, environment : {env}")
    if env:
        env = Env(env)
        url = env.see
    token = getToken(url)
    if keyWord in ['ZooKeeper', 'RabbitMQ', 'Redis']:
        component_list = getComponent(url, token)
        instanceId = component_list.get(keyWord)
        #查看服务状态，如果状态是100，表示服务正在运行中，如果不是100，重启服务
        res_status = getComponentStatus(url, token, instanceId).json()
        sta = res_status['data'][f'#{instanceId}']['runningState']
        if sta == '100':
            logger.info(f"============组件{keyWord} 正在运行！！=========")
            return {keyWord: True}
        else:
            res_list = restartComponent(url, token, instanceId).json()
            if res_list.get('message') == 'success':
                logger.info(f"============组件{keyWord}开始重启！！=========")
                for i in range(12):
                    res_status = getComponentStatus(url, token, instanceId).json()
                    # logger.info(res_status['data'][f'#{instanceId}']['runningState'])
                    if res_status['data'][f'#{instanceId}']['runningState'] == '100':
                        logger.info(f"============组件{keyWord}重启成功！！=========")
                        return {keyWord: True}
                    else:
                        time.sleep(10)
                        if i == 11:
                            logger.info(f"============注意！！！组件{keyWord} 2分钟内未重启成功！！=========")
                            return {keyWord: True}
            else:
                logger.info(f"============组件{keyWord}重启失败！！=========")
                return {keyWord: False}
    else:
        response = getServer(url, token, keyWord)
        result = json.loads(response.text)
        # logger.info(result)
        if result['data']['items']:
            id = result['data']['items'][0]['id']
            response = getServerStatics(url, token, id)
            results = response.json()
            if results['data'][0]['filnal_status'] == 0:
                logger.info(f"============服务{result['data']['items'][0]['name']} 正在运行！！=========")
                return {keyWord: True}
            else:
                restartServer(url, token, id)
                logger.info(f"============{result['data']['items'][0]['name']}开始重启！！=========")
                temp = 0
                while temp< 19:
                    sleep(10)
                    response = getServerStatics(url, token, id)
                    result1 = response.json()
                    # logger.info(result1)
                    # if result1['data']['success'] == 1:
                    if result1['data'][0]['filnal_status'] == 0:
                        logger.info(f"============{result['data']['items'][0]['name']}重启成功！！=========")
                        break
                    else:
                        temp = temp + 1
                if temp == 18:
                    logger.info(f"============注意！！{result['data']['items'][0]['name']} 三分钟内未启动完成！！=========")
                return {keyWord: True}
        else:
            logger.info(f"============{keyWord}服务不存在，请确认！=========")
            return {keyWord: False}


def getComponent(url, token):
    """
    获取组件instanceId
    """
    headers['Authorization'] = token
    getUrl = url.replace("/app.htm", "/component/ZooKeeper/authority/getList.json")
    data ={}
    test = APIRequset(getUrl, data, headers)
    res = test.doGet()
    result = res.json()['data']
    for i in result:
        key = i['name'].split('-')[0]
        value = i['instanceId'].replace('#','')
        data.update({key:value})
    return data


def restartComponent(url,token,keyWord):
    """
    重启组件服务
    """
    headers['Authorization'] = token
    getUrl = url.replace("/app.htm", "/component/restartApp.json")
    data = {'appId': keyWord}
    test = APIRequset(getUrl, data, headers)
    return test.doPost()

def getComponentStatus(url,token,keyWord):
    """
    获取组件状态
    """
    headers['Authorization'] = token
    getUrl = url.replace("/app.htm", "/component/getComponentAppStatus.json")
    data = {'ids':f'#{keyWord}'}
    test = APIRequset(getUrl, data, headers)
    return test.doPost()


def installComponent(url,token,keyWord,instanceId):
    """
    部署组件服务：ZooKeeper|RabbitMQ|Redis
    """
    headers['Authorization'] = token
    getUrl = url.replace("/app.htm", "/component/installComponent.json")
    data = {'instanceId':f'#{instanceId}','serviceType':f'{keyWord}'}
    test = APIRequset(getUrl, data, headers)
    return test.doPost()

def installServer(url,keyWord,env=None):
    if env:
        env=Env(env)
        url=env.see
    token = getToken(url)
    if keyWord in ['ZooKeeper','RabbitMQ','Redis']:
        component_list = getComponent(url, token)
        instanceId = component_list.get(keyWord)
        installComponent(url, token, keyWord, instanceId)
        time.sleep(30)


def read_file(filepath):
    '''
     读取json文件，返回json数据
    '''
    with open(filepath, 'r', encoding='utf-8') as f:
        content = f.read()
        # logger.info(type(content))
        return content


if __name__=='__main__':
    f_path = f'{os.getcwd()}\config.txt'
    text = read_file(f_path)
    read_list = text.split('list =')
    url = read_list[0].replace('\\n', '').split('=')[1].strip()
    serverList =read_list[1].replace('\\n', '').strip()
    #url为效能跳转see平台的链接
    # url = "http://b980066487074b7fba467c87503e9bab.vm-a.hep.see.dev.hundsun.com/acm/app.htm#/dashboard/application/list"
    #服务名称汇总
    list = eval(serverList)
    # 依次重启全部服务，10秒循环查询一次服务是否重启成功，重启成功继续重启下一个服务
    # 3分钟内服务未重启完成，输出服务状态，继续重启下一个服务
    # restart(url,  ['amlcrs-server'])
    print(list)
    for keyword in list:
        restart(url, keyword)



